﻿#region -- 版 本 注 释 --
/****************************************************
* 文 件 名：
* Copyright(c) 王树羽
* CLR 版本: 4.5
* 创 建 人：王树羽
* 电子邮箱：674613047@qq.com
* 官方网站：https://www.cnblogs.com/shuyu
* 创建日期：2018-06-25 
* 文件描述：
******************************************************
* 修 改 人：
* 修改日期：
* 备注描述：
*******************************************************/
#endregion

using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Reflection;
using System.Text;

namespace CommonLib
{
    /// <summary>
    /// List集合操作帮助类
    /// </summary>
    public class ListHelper
    {
        #region 赋值转换

        /// <summary>
        /// A实体转换成B实体
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="K"></typeparam>
        /// <param name="source">原始数据对象</param>
        /// <param name="target">目标对象</param>
        /// <returns></returns>
        public static K EntityToEntity<T, K>(T source, K target) where T : class, new() where K : class
        {
            if (source != null && target != null)
            {
                PropertyInfo[] propertys1 = source.GetType().GetProperties();// 获得此模型的公共属性
                PropertyInfo[] propertys = target.GetType().GetProperties();
                foreach (PropertyInfo pi in propertys)
                {
                    if (pi.CanWrite && propertys1.Where(ex => ex.Name == pi.Name).Count() > 0)
                    {
                        object value = GetProperty(source, pi.Name);
                        pi.SetValue(target, value, null);
                    }
                }
            }
            return target;
        }

        /// <summary>
        /// A集合转换成B集合
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="K"></typeparam>
        /// <param name="source">源数据对象</param>
        /// <param name="target">赋值目标对象</param>
        public static List<K> ListToList<T, K>(List<T> source, List<K> target) where T : class, new() where K : class, new()
        {
            if (source != null && target != null)
            {
                foreach (var item in source)
                {
                    var obj = new K();
                    EntityToEntity(item, obj);
                    target.Add(obj);
                }
                return target;
            }
            return null;
        }
        #endregion

        #region 属性设置 取值 

        /// <summary>
        /// 实体获取属性值
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="source"></param>
        /// <param name="Name"></param>
        /// <returns></returns>
        public static object GetProperty<T>(T source, string Name) where T : class, new()
        {
            PropertyInfo[] propertys = source.GetType().GetProperties();// 获得此模型的公共属性
            PropertyInfo pi = propertys.Where(ex => ex.Name == Name).FirstOrDefault();
            if (pi != null)
            {
                return pi.GetValue(source, null);
            }
            return null;
        }

        /// <summary>
        /// 实体设置赋值
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="source"></param>
        /// <param name="Name"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static bool SetProperty<T>(T source, string Name, object value) where T : class, new()
        {
            try
            {
                PropertyInfo[] propertys = source.GetType().GetProperties();// 获得此模型的公共属性
                PropertyInfo pi = propertys.Where(ex => ex.Name == Name).FirstOrDefault();
                if (pi != null)
                {
                    pi.SetValue(source, value, null);
                }
                return true;
            }
            catch
            {
                return false;
            }
        }
        #endregion

        #region List<T>集合转DataTable

        /// <summary>
        /// List集合转DataTable
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="list"></param>
        /// <returns></returns>
        public static DataTable ListToDataTable<T>(List<T> list) where T : class, new()
        {
            var Dt = new DataTable(typeof(T).Name);
            PropertyInfo[] propertyInfo = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);

            foreach (PropertyInfo prop in propertyInfo)
            {
                Type t = GetCoreType(prop.PropertyType);
                Dt.Columns.Add(prop.Name, t);
            }

            foreach (T item in list)
            {
                var values = new object[propertyInfo.Length];
                for (int i = 0; i < propertyInfo.Length; i++)
                {
                    values[i] = propertyInfo[i].GetValue(item, null);
                }
                Dt.Rows.Add(values);
            }
            return Dt;
        }

        /// <summary>
        /// 如果类型为空否则返回类型返回基本类型
        /// </summary>
        /// <param name="t"></param>
        /// <returns></returns>
        private static Type GetCoreType(Type t)
        {
            var flag = !t.IsValueType || (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Nullable<>));//判断属性是否为空
            if (t != null && flag)
            {
                if (t.IsValueType)//值类型
                {
                    return Nullable.GetUnderlyingType(t);
                }
            }
            return t;
        }

        #endregion 

        #region 集合值对比

        /// <summary>
        /// 集合差异比较器,比较两个实体集合值是否一样,
        /// true 存在差异 false 不存在差异
        /// </summary>
        /// <param name="source">源版本实体集合</param>
        /// <param name="current">当前版本实体集合</param>
        /// <returns>true 存在差异 false 不存在差异</returns>
        public static bool ModelComparison<T1, T2>(List<T1> source, List<T2> current) where T1 : class where T2 : class
        {
            if (source.Count != current.Count) { return true; }
            for (int i = 0; i < source.Count; i++)
            {
                bool flag = ModelComparison(source[i], current[i]);
                if (flag) { return flag; }
            }
            return false;
        }

        /// <summary>
        /// 实体差异比较器,true 存在差异 false 不存在差异
        /// </summary>
        /// <param name="source">源版本实体</param>
        /// <param name="current">当前版本实体</param>
        /// <returns>true 存在差异 false 不存在差异</returns>
        public static bool ModelComparison<T1, T2>(T1 source, T2 current) where T1 : class where T2 : class
        {
            Type t1 = source.GetType();
            Type t2 = current.GetType();
            PropertyInfo[] property1 = t1.GetProperties();
            //排除主键和基础字段 
            foreach (PropertyInfo p in property1)
            {
                string name = p.Name;
                string value1 = p.GetValue(source, null)?.ToString();
                string value2 = t2.GetProperty(name)?.GetValue(current, null)?.ToString();
                if (value1 != value2)
                {
                    return true;
                }
            }
            return false;
        }

        #endregion
    }
}
